package com.jtcoding.chat.service.impl;

import com.jtcoding.chat.common.FileUtils;
import com.jtcoding.chat.common.JacksonSerializer;
import com.jtcoding.chat.common.QRcodeUtils;
import com.jtcoding.chat.common.enums.ServiceEnum;
import com.jtcoding.chat.common.enums.ServiceTypeEnum;
import com.jtcoding.chat.exception.ApiException;
import com.jtcoding.chat.common.enums.ResultCode;
import com.jtcoding.chat.dao.chat.UserDao;
import com.jtcoding.chat.model.FastDFSResource;
import com.jtcoding.chat.model.ResourceLog;
import com.jtcoding.chat.model.User;
import com.jtcoding.chat.service.MailService;
import com.jtcoding.chat.service.ResourceService;
import com.jtcoding.chat.service.UserService;
import org.csource.common.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;

import static com.jtcoding.chat.common.enums.ResultCode.*;

/**
 * @author jason.tang
 * @create 2018-12-27 13:01
 * @description
 */

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private MailService mailService;

    @Override
    public User userLogin(User user) {
        User tempUser = userDao.getUserByLoginIDAndPwd(user)
                .orElseThrow(() -> new ApiException(USER_LOGIN_ERROR));

        if (tempUser.getStatus().equals(USER_STATUS_DIS)) {
            throw new ApiException("此用户已停用，请重新注册或者联系管理员...");
        }
        if (tempUser.getStatus().equals(USER_STATUS_RSC) || tempUser.getStatus().equals(USER_STATUS_PAT)) {
            throw new ApiException("当前登录用户暂未激活，请激活后登录...");
        }
        return tempUser;
    }

    @Transactional
    @Override
    public User addUser(User user) throws Exception {
        Optional.of(user).orElseThrow(() -> new ApiException(ResultCode.PARAM_IS_INVALID));

        userDao.getUserByNewInfo(user)
                .orElseThrow(() -> new ApiException(ResultCode.EMAIL_PHONE_ALREADY_EXISTS));

        user.setIconURL("http://www.jtcoding.cn/group1/M00/00/00/rBIcWlxg8OiAQ-BcAALL1A93_3o247.png");
        user.setStatus(USER_STATUS_RSC);
        user.setCreateDateTime(LocalDateTime.now());
        user.setUsername("CHAT_" + user.getLoginEmail().split("@")[0]);
        user.setSignature("这个人很懒，什么也没留下~~~");
        int rtn = userDao.addUser(user);
        if (rtn == 0) {
            throw new ApiException(ResultCode.OPERATION_FAILURE);
        }
        this.modifyQRCode(user.getUserNum());
        mailService.putUser(user);
        return user;
    }

    @Transactional
    @Override
    public Map<String, Object> modifyUsername(User user) {
        if (user.getUserNum() == null || user.getUsername() == null || user.getUsername().length() == 0) {
            throw new ApiException(PARAM_IS_INVALID);
        }
        int rtn = userDao.updateUsername(user.getUserNum(), user.getUsername());
        if (rtn == 0) {
            throw new ApiException(OPERATION_FAILURE);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("username", user.getUsername());
        return resultMap;
    }

    @Override
    public List<User> getUserByNums(Integer... friendNum) {
        return userDao.getUserByNums(friendNum);
    }

    @Override
    public List<User> searchUser(String username) {
        username = "%" + username + "%";
        return userDao.searchUser(username);
    }

    @Override
    public User getUserByNum(Integer userNum) {
        return userDao.getUserByUserNum(userNum).get();
    }

    @Transactional
    @Override
    public Boolean activationUser(Integer userNum) {
        User user = userDao.getUserByUserNum(userNum)
                .orElseThrow(() -> new ApiException(PARAM_IS_INVALID));
        if (user.getStatus().equals(USER_STATUS_ACT)) {
            throw new ApiException("此帐号已激活，请勿重复操作！");
        }
        if (user.getStatus().equals(USER_STATUS_DIS)) {
            throw new ApiException("此帐号已停止使用，操作失败！");
        }
        if (user.getStatus().equals(USER_STATUS_RSC)) {
            throw new ApiException("系统还未发送激活邮件，请勿错误操作！");
        }
        user.setStatus(USER_STATUS_ACT);
        return userDao.updateUserStatus(user) > 0;
    }

    @Transactional
    @Override
    public int modifyUserStatus(User user) {
        return userDao.updateUserStatus(user);
    }

    @Transactional
    @Override
    public Map<String, Object> modifySignature(User user) {
        if (user == null || user.getSignature().isEmpty() || user.getUserNum() == null) {
            throw new ApiException(PARAM_IS_INVALID);
        }
        int rtn = userDao.updateSignature(user);
        if (rtn == 0) {
            throw new ApiException(OPERATION_FAILURE);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("signature", user.getSignature());
        return resultMap;
    }

    @Override
    public Map<String, Object> modifyUserPortrait(Integer userNum, MultipartFile file) throws IOException, MyException {
        User user = userDao.getUserByUserNum(userNum)
                .orElseThrow(() -> new ApiException(ResultCode.PARAM_IS_INVALID));
        String filename = file.getOriginalFilename();
        String exc = filename.substring(filename.lastIndexOf(".") + 1);
        if (!Arrays.asList(ResourceService.PIC_EXC).contains(exc)) {
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < ResourceService.PIC_EXC.length; i++) {
                if (i == ResourceService.PIC_EXC.length - 1) {
                    result.append(ResourceService.PIC_EXC[i]);
                } else {
                    result.append(ResourceService.PIC_EXC[i]).append(", ");
                }

            }
            throw new ApiException("文件格式错误，支持的格式为：" + result.toString());
        }
        FastDFSResource resource = FastDFSResource.builder()
                .fromService(ServiceEnum.CHAT.value()).refNum(userNum)
                .resType(ServiceTypeEnum.ICON.value()).content(file.getBytes())
                .name(filename).build();
        ResourceLog resourceLog = resourceService.uploadResource(resource);
        user.setIconURL(resourceLog.getResURL());
        int rtn = userDao.updateUserIcon(user);
        if (rtn == 0) {
            throw new ApiException(OPERATION_FAILURE);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("iconURL", user.getIconURL());
        return resultMap;
    }

    @Transactional
    @Override
    public Map<String, Object> modifyQRCode(Integer userNum) throws Exception {
        User user = userDao.getUserByUserNum(userNum)
                .orElseThrow(() -> new ApiException(ResultCode.PARAM_IS_INVALID));
        String qrcodeURL = this.generateQRcodeURL(user.getUserNum(), user.getIconURL());
        user.setQrcodeURL(qrcodeURL);
        int rtn = userDao.updateUserQRCode(user);
        if (rtn == 0) {
            throw new ApiException(OPERATION_FAILURE);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("qrcodeURL", user.getQrcodeURL());
        return resultMap;
    }

    private String generateQRcodeURL(Integer userNum, String iconURL) throws Exception {
        URL url = new URL(iconURL);
        File qrcodeFile = QRcodeUtils.generateQRCodeFile(500, 500, url, String.valueOf(userNum));
        byte[] bytes = FileUtils.fileToBytes(qrcodeFile);

        FastDFSResource resource = FastDFSResource.builder()
                .fromService(ServiceEnum.CHAT.value()).refNum(userNum)
                .resType(ServiceTypeEnum.QRCODE.value()).content(bytes)
                .name(qrcodeFile.getName()).build();
        ResourceLog resourceLog = resourceService.uploadResource(resource);

        if (resourceLog != null) {
            return resourceLog.getResURL();
        }
        throw new ApiException("二维码生成失败！");
    }
}